﻿using Communergy.Repository;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Communergy.Common;
using System.Collections.Generic;
using System;
using Communergy.UnitTesting;
using System.Configuration;
using System.Linq;
using Communergy.Repository.EntityFramework;

namespace CommunergyLogicTests
{
    
    
    /// <summary>
    ///This is a test class for EntityAutomaticRepositoryTest and is intended
    ///to contain all EntityAutomaticRepositoryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class EntityAutomaticRepositoryTest
    {
        int maxRandomRecords = 10;

      

        /// <summary>
        ///A test for Insert_ElectricityRealtime
        ///</summary>
        [TestMethod()]
        public void Insert_ElectricityRealtimeTest()
        {
            //create new meter
            communergyEntities db = new communergyEntities();
            var meterGuid = Guid.NewGuid();

            var newMeter = new ElectricityMeter
            {
                me_meterGuid = meterGuid,
                me_meterName = UnitTestHelper.RandomString(15)
            };
            db.AddToElectricityMeter(newMeter);
            db.SaveChanges();

            Assert.AreEqual(0, newMeter.ElectricityRealtime.Count);

            //var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;


            EntityRealtimeRepository target = new EntityRealtimeRepository(db);
            string meterId = meterGuid.ToString();

            List<RealtimeEnergyReading> newRealtimeEnergyReadings = new List<RealtimeEnergyReading>();
            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(maxRandomRecords);
            int interval = 6;

            int totalJoules = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                RealtimeEnergyReading newReading = new RealtimeEnergyReading();
                var newReadingIntervalfromStart = i * 6;
                newReading.ReadingDateTime = baseDateTime.AddSeconds(newReadingIntervalfromStart);
                var reading = UnitTestHelper.RandomInt(100, 1000);
                newReading.Watts = reading;
                var joules = reading * interval;
                newReading.Joules = joules;
                totalJoules += joules;
                newRealtimeEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalJoules > 0);

            //add them for the first time
            target.Insert_ElectricityRealtime(meterId, newRealtimeEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityRealtime").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityRealtime.Count);

            var totalDbJoules = readMeter.ElectricityRealtime.Sum(er => er.cc_joules);
            Assert.AreEqual(totalJoules, totalDbJoules);

            var savedRecords = readMeter.ElectricityRealtime.OrderBy(r => r.cc_dateTime).ToList();

            int recordNumber=0;
            foreach (var expected in newRealtimeEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.ToString(), savedRecord.cc_dateTime.ToString());
                Assert.AreEqual(expected.Joules, savedRecord.cc_joules);
                Assert.AreEqual(expected.Watts, savedRecord.cc_watts);
                recordNumber++;
            }
        }


       //attempt to add the same data twice - will only be added once
        [TestMethod()]
        public void Insert_ElectricityRealtimeTestDoubleUp()
        {
            //create new meter
            communergyEntities db = new communergyEntities();
            var meterGuid = Guid.NewGuid();

            var newMeter = new ElectricityMeter
            {
                me_meterGuid = meterGuid,
                me_meterName = UnitTestHelper.RandomString(15)
            };
            db.AddToElectricityMeter(newMeter);
            db.SaveChanges();

            Assert.AreEqual(0, newMeter.ElectricityRealtime.Count);

            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;


            EntityRealtimeRepository target = new EntityRealtimeRepository(db); 
            string meterId = meterGuid.ToString();

            List<RealtimeEnergyReading> newRealtimeEnergyReadings = new List<RealtimeEnergyReading>();
            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(1,maxRandomRecords);
            int interval = 6;

            int totalJoules = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                RealtimeEnergyReading newReading = new RealtimeEnergyReading();
                var newReadingIntervalfromStart = i * 6;
                newReading.ReadingDateTime = baseDateTime.AddSeconds(newReadingIntervalfromStart);
                var reading = UnitTestHelper.RandomInt(100, 1000);
                newReading.Watts = reading;
                var joules = reading * interval;
                newReading.Joules = joules;
                totalJoules += joules;
                newRealtimeEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalJoules > 0);

            //add them for the first time
            target.Insert_ElectricityRealtime(meterId, newRealtimeEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityRealtime").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityRealtime.Count);

            var totalDbJoules = readMeter.ElectricityRealtime.Sum(er => er.cc_joules);
            Assert.AreEqual(totalJoules, totalDbJoules);


            ////add them for the second time
            target.Insert_ElectricityRealtime(meterId, newRealtimeEnergyReadings);

            communergyEntities readDb2 = new communergyEntities();
            var readMeter2 = readDb.ElectricityMeter.Include("ElectricityRealtime").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter2);
            Assert.AreEqual(recordsToCreate, readMeter2.ElectricityRealtime.Count);

            var totalDbJoules2 = readMeter2.ElectricityRealtime.Sum(er => er.cc_joules);
            Assert.AreEqual(totalJoules, totalDbJoules2);
        }

        /// <summary>
        ///A test for Insert_ElectricityHourly
        ///</summary>
        [TestMethod()]
        public void Insert_ElectricityHourlyTest()
        {
            var newMeter = CommunergyTestHelper.GetRandomMeter();
            var meterGuid = newMeter.me_meterGuid;
            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;
            IUnitOfWork db = new communergyEntities(connString);
            EntityHistoricRepository target = new EntityHistoricRepository(db); 
            string meterId = meterGuid.ToString();

            List<HistoricalEnergyReading> hourlyEnergyReadings = new List<HistoricalEnergyReading>();

            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(maxRandomRecords);

            decimal totalkWH = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                HistoricalEnergyReading newReading = new HistoricalEnergyReading();
                
                newReading.ReadingDateTime = baseDateTime.AddHours(i);
                var reading = (decimal)UnitTestHelper.RandomInt(100, 1000)/100;
                newReading.KWh = reading;

                totalkWH += reading;
                hourlyEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalkWH > 0);

            //add them for the first time
            target.Insert_ElectricityHourly(meterId, hourlyEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityHourly_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityHourly_Auto.Count);

            var totalDbkWh =readMeter.ElectricityHourly_Auto.Sum(er => er.ah_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh);

            var savedRecords = readMeter.ElectricityHourly_Auto.OrderBy(r => r.ah_hour).ToList();
            int recordNumber = 0;
            foreach (var expected in hourlyEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.ToString(), savedRecord.ah_hour.ToString());
                Assert.AreEqual(expected.KWh, savedRecord.ah_kWh);
                recordNumber++;
            }
        }

        [TestMethod()]
        public void Insert_ElectricityHourlyTest_DoubleUp()
        {
            var newMeter = CommunergyTestHelper.GetRandomMeter();
            var meterGuid = newMeter.me_meterGuid;
            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;
            IUnitOfWork db = new communergyEntities(connString);
            EntityHistoricRepository target = new EntityHistoricRepository(db); 
            string meterId = meterGuid.ToString();

            List<HistoricalEnergyReading> hourlyEnergyReadings = new List<HistoricalEnergyReading>();

            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(maxRandomRecords);

            decimal totalkWH = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                HistoricalEnergyReading newReading = new HistoricalEnergyReading();

                newReading.ReadingDateTime = baseDateTime.AddHours(i);
                var reading = (decimal)UnitTestHelper.RandomInt(100, 1000) / 100;
                newReading.KWh = reading;

                totalkWH += reading;
                hourlyEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalkWH > 0);

            //add them for the first time
            target.Insert_ElectricityHourly(meterId, hourlyEnergyReadings);
            db.Save();

            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityHourly_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityHourly_Auto.Count);

            var totalDbkWh = readMeter.ElectricityHourly_Auto.Sum(er => er.ah_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh);

            //insert twice
            target.Insert_ElectricityHourly(meterId, hourlyEnergyReadings);
            db.Save();

            communergyEntities readDb2 = new communergyEntities();
            var readMeter2 = readDb2.ElectricityMeter.Include("ElectricityHourly_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter2);
            Assert.AreEqual(recordsToCreate, readMeter2.ElectricityHourly_Auto.Count);

            var totalDbkWh2 = readMeter2.ElectricityHourly_Auto.Sum(er => er.ah_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh2);

            var totalSavedRecords = readMeter2.ElectricityHourly_Auto.Count;
            Assert.AreEqual(recordsToCreate, totalSavedRecords);
            
            
            //check all records saved correctly
            var savedRecords = readMeter.ElectricityHourly_Auto.OrderBy(r => r.ah_hour).ToList();
            int recordNumber = 0;
            foreach (var expected in hourlyEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.ToString(), savedRecord.ah_hour.ToString());
                Assert.AreEqual(expected.KWh, savedRecord.ah_kWh);
                recordNumber++;
            }
        }

        /// <summary>
        ///A test for Insert_ElectricityDaily
        ///</summary>
        [TestMethod()]
        public void Insert_ElectricityDailyTest()
        {
            var newMeter = CommunergyTestHelper.GetRandomMeter();
            var meterGuid = newMeter.me_meterGuid;
            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;
            var db = new communergyEntities(connString);
            EntityHistoricRepository target = new EntityHistoricRepository(db); 
            string meterId = meterGuid.ToString();

            List<HistoricalEnergyReading> dailyEnergyReadings = new List<HistoricalEnergyReading>();
            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(1, maxRandomRecords);

            decimal totalkWH = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                HistoricalEnergyReading newReading = new HistoricalEnergyReading();

                newReading.ReadingDateTime = baseDateTime.AddDays(i);
                var reading = (decimal)UnitTestHelper.RandomInt(100, 1000) / 100;
                newReading.KWh = reading;

                totalkWH += reading;
                dailyEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalkWH > 0);

            //add them for the first time
            target.Insert_ElectricityDaily(meterId, dailyEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityDaily_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityDaily_Auto.Count);

            var totalDbkWh = readMeter.ElectricityDaily_Auto.Sum(er => er.ad_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh);

            var savedRecords = readMeter.ElectricityDaily_Auto.OrderBy(r => r.ad_day).ToList();
            int recordNumber = 0;
            foreach (var expected in dailyEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.Date.ToString(), savedRecord.ad_day.ToString());
                Assert.AreEqual(expected.KWh, savedRecord.ad_kWh);
                recordNumber++;
            }
        }

        [TestMethod()]
        public void Insert_ElectricityDailyTest_DoubleUp()
        {
            var newMeter = CommunergyTestHelper.GetRandomMeter();
            var meterGuid = newMeter.me_meterGuid;
            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;
            var db = new communergyEntities(connString);
            EntityHistoricRepository target = new EntityHistoricRepository(db); 
            string meterId = meterGuid.ToString();
            
            List<HistoricalEnergyReading> dailyEnergyReadings = new List<HistoricalEnergyReading>();
            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(maxRandomRecords);

            decimal totalkWH = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                HistoricalEnergyReading newReading = new HistoricalEnergyReading();

                newReading.ReadingDateTime = baseDateTime.AddDays(i);
                var reading = (decimal)UnitTestHelper.RandomInt(100, 1000) / 100;
                newReading.KWh = reading;

                totalkWH += reading;
                dailyEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalkWH > 0);

            //add them for the first time
            target.Insert_ElectricityDaily(meterId, dailyEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityDaily_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityDaily_Auto.Count);

            var totalDbkWh = readMeter.ElectricityDaily_Auto.Sum(er => er.ad_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh);


            //insert twice
            target.Insert_ElectricityHourly(meterId, dailyEnergyReadings);
            db.Save();
            communergyEntities readDb2 = new communergyEntities();
            var readMeter2 = readDb2.ElectricityMeter.Include("ElectricityDaily_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter2);
            Assert.AreEqual(recordsToCreate, readMeter2.ElectricityDaily_Auto.Count);

            var totalDbkWh2 = readMeter2.ElectricityDaily_Auto.Sum(er => er.ad_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh2);

            var totalSavedRecords = readMeter2.ElectricityDaily_Auto.Count;
            Assert.AreEqual(recordsToCreate, totalSavedRecords);


            var savedRecords = readMeter.ElectricityDaily_Auto.OrderBy(r => r.ad_day).ToList();
            int recordNumber = 0;
            foreach (var expected in dailyEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.Date.ToString(), savedRecord.ad_day.ToString());
                Assert.AreEqual(expected.KWh, savedRecord.ad_kWh);
                recordNumber++;

            }


        }

        /// <summary>
        ///A test for Insert_ElectricityMonthly
        ///</summary>
        [TestMethod()]
        public void Insert_ElectricityMonthlyTest()
        {
            var newMeter = CommunergyTestHelper.GetRandomMeter();
            var meterGuid = newMeter.me_meterGuid;
            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;
            IUnitOfWork db = new communergyEntities(connString);
            EntityHistoricRepository target = new EntityHistoricRepository(db); 
            string meterId = meterGuid.ToString();

            List<HistoricalEnergyReading> monthlyEnergyReadings = new List<HistoricalEnergyReading>();
            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(maxRandomRecords);

            decimal totalkWH = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                HistoricalEnergyReading newReading = new HistoricalEnergyReading();

                newReading.ReadingDateTime = baseDateTime.AddMonths(i);
                var reading = (decimal)UnitTestHelper.RandomInt(100, 1000) / 100;
                newReading.KWh = reading;

                totalkWH += reading;
                monthlyEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalkWH > 0);

            //add them for the first time
            target.Insert_ElectricityMonthly(meterId, monthlyEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityMonthly_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityMonthly_Auto.Count);

            var totalDbkWh = readMeter.ElectricityMonthly_Auto.Sum(er => er.am_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh);


            //insert twice
            target.Insert_ElectricityMonthly(meterId, monthlyEnergyReadings);
            communergyEntities readDb2 = new communergyEntities();
            var readMeter2 = readDb2.ElectricityMeter.Include("ElectricityMonthly_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter2);
            Assert.AreEqual(recordsToCreate, readMeter2.ElectricityMonthly_Auto.Count);

            var totalDbkWh2 = readMeter2.ElectricityMonthly_Auto.Sum(er => er.am_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh2);

            var totalSavedRecords = readMeter2.ElectricityMonthly_Auto.Count;
            Assert.AreEqual(recordsToCreate, totalSavedRecords);

            var savedRecords = readMeter.ElectricityMonthly_Auto.OrderBy(r => r.am_month).ToList();
            int recordNumber = 0;
            foreach (var expected in monthlyEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.Date.ToString(), savedRecord.am_month.ToString());
                Assert.AreEqual(expected.KWh, savedRecord.am_kWh);
                recordNumber++;
            }
        }

        /// <summary>
        ///A test for Insert_ElectricityMonthly
        ///</summary>
        [TestMethod()]
        public void Insert_ElectricityMonthlyTest_DoubleUp()
        {
            var newMeter = CommunergyTestHelper.GetRandomMeter();
            var meterGuid = newMeter.me_meterGuid;
            var connString = ConfigurationManager.ConnectionStrings["communergyEntities"].ConnectionString;
            IUnitOfWork db = new communergyEntities(connString);
            EntityHistoricRepository target = new EntityHistoricRepository(db); 
            string meterId = meterGuid.ToString();

            List<HistoricalEnergyReading> monthlyEnergyReadings = new List<HistoricalEnergyReading>();
            DateTime baseDateTime = DateTime.Now;

            int recordsToCreate = UnitTestHelper.RandomInt(maxRandomRecords);

            decimal totalkWH = 0;
            for (int i = 0; i < recordsToCreate; i++)
            {
                HistoricalEnergyReading newReading = new HistoricalEnergyReading();

                newReading.ReadingDateTime = baseDateTime.AddMonths(i);
                var reading = (decimal)UnitTestHelper.RandomInt(100, 1000) / 100;
                newReading.KWh = reading;

                totalkWH += reading;
                monthlyEnergyReadings.Add(newReading);
            }
            Assert.IsTrue(totalkWH > 0);

            //add them for the first time
            target.Insert_ElectricityMonthly(meterId, monthlyEnergyReadings);
            db.Save();
            communergyEntities readDb = new communergyEntities();
            var readMeter = readDb.ElectricityMeter.Include("ElectricityMonthly_Auto").Where(m => m.me_meterGuid == meterGuid).FirstOrDefault();
            Assert.IsNotNull(readMeter);
            Assert.AreEqual(recordsToCreate, readMeter.ElectricityMonthly_Auto.Count);

            var totalDbkWh = readMeter.ElectricityMonthly_Auto.Sum(er => er.am_kWh);
            Assert.AreEqual(totalkWH, totalDbkWh);

            var savedRecords = readMeter.ElectricityMonthly_Auto.OrderBy(r => r.am_month).ToList();
            int recordNumber = 0;
            foreach (var expected in monthlyEnergyReadings)
            {
                var savedRecord = savedRecords[recordNumber];
                Assert.AreEqual(expected.ReadingDateTime.Date.ToString(), savedRecord.am_month.ToString());
                Assert.AreEqual(expected.KWh, savedRecord.am_kWh);
                recordNumber++;
            }

        }
    }
}
